/**************************************************************************
 *
 * Copyright (c) 2017-2021, luotang.me <wypx520@gmail.com>, China.
 * All rights reserved.
 *
 * Distributed under the terms of the GNU General Public License v2.
 *
 * This software is provided 'as is' with no explicit or implied warranties
 * in respect of its properties, including, but not limited to, correctness
 * and/or fitness for purpose.
 *
 **************************************************************************/
#ifndef BASE_WEAKCALLBACK_H_
#define BASE_WEAKCALLBACK_H_

#include <functional>
#include <memory>

namespace MSF {
// A barely usable WeakCallback

template <typename CLASS, typename... ARGS>
class WeakCallback {
 public:
  WeakCallback(const std::weak_ptr<CLASS>& object,
               const std::function<void(CLASS*, ARGS...)>& function)
      : object_(object), function_(function) {}

  // Default dtor, copy ctor and assignment are okay

  void operator()(ARGS&&... args) const {
    std::shared_ptr<CLASS> ptr(object_.lock());
    if (ptr) {
      function_(ptr.get(), std::forward<ARGS>(args)...);
    }
    // else
    // {
    //   LOG_TRACE << "expired";
    // }
  }

 private:
  std::weak_ptr<CLASS> object_;
  std::function<void(CLASS*, ARGS...)> function_;
};

template <typename CLASS, typename... ARGS>
WeakCallback<CLASS, ARGS...> makeWeakCallback(
    const std::shared_ptr<CLASS>& object, void (CLASS::*function)(ARGS...)) {
  return WeakCallback<CLASS, ARGS...>(object, function);
}

template <typename CLASS, typename... ARGS>
WeakCallback<CLASS, ARGS...> makeWeakCallback(
    const std::shared_ptr<CLASS>& object,
    void (CLASS::*function)(ARGS...) const) {
  return WeakCallback<CLASS, ARGS...>(object, function);
}

}  // namespace MSF
#endif